"""
AI Agent Pro - 异常处理模块
"""

import traceback
from typing import Any, Dict, Optional, Union

from fastapi import FastAPI, HTTPException, Request, status
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import ValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException

from app.core.logging import get_logger, log_security_event

logger = get_logger(__name__)


class AgentException(Exception):
    """智能体基础异常类"""
    
    def __init__(
        self,
        message: str,
        error_code: str = "AGENT_ERROR",
        details: Optional[Dict[str, Any]] = None,
        status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR
    ):
        self.message = message
        self.error_code = error_code
        self.details = details or {}
        self.status_code = status_code
        super().__init__(self.message)


class AgentNotFoundError(AgentException):
    """智能体未找到异常"""
    
    def __init__(self, agent_id: str):
        super().__init__(
            message=f"智能体 {agent_id} 未找到",
            error_code="AGENT_NOT_FOUND",
            details={"agent_id": agent_id},
            status_code=status.HTTP_404_NOT_FOUND
        )


class AgentCreationError(AgentException):
    """智能体创建异常"""
    
    def __init__(self, reason: str):
        super().__init__(
            message=f"智能体创建失败: {reason}",
            error_code="AGENT_CREATION_FAILED",
            details={"reason": reason},
            status_code=status.HTTP_400_BAD_REQUEST
        )


class ModelError(AgentException):
    """AI模型异常"""
    
    def __init__(self, model_name: str, reason: str):
        super().__init__(
            message=f"模型 {model_name} 错误: {reason}",
            error_code="MODEL_ERROR",
            details={"model": model_name, "reason": reason},
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE
        )


class ToolError(AgentException):
    """工具执行异常"""
    
    def __init__(self, tool_name: str, reason: str):
        super().__init__(
            message=f"工具 {tool_name} 执行失败: {reason}",
            error_code="TOOL_ERROR",
            details={"tool": tool_name, "reason": reason},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


class MemoryError(AgentException):
    """记忆系统异常"""
    
    def __init__(self, operation: str, reason: str):
        super().__init__(
            message=f"记忆操作 {operation} 失败: {reason}",
            error_code="MEMORY_ERROR",
            details={"operation": operation, "reason": reason},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


class AuthenticationError(AgentException):
    """认证异常"""
    
    def __init__(self, reason: str = "认证失败"):
        super().__init__(
            message=reason,
            error_code="AUTHENTICATION_ERROR",
            status_code=status.HTTP_401_UNAUTHORIZED
        )


class AuthorizationError(AgentException):
    """授权异常"""
    
    def __init__(self, resource: str, action: str):
        super().__init__(
            message=f"没有权限访问资源 {resource} 执行操作 {action}",
            error_code="AUTHORIZATION_ERROR",
            details={"resource": resource, "action": action},
            status_code=status.HTTP_403_FORBIDDEN
        )


class RateLimitError(AgentException):
    """速率限制异常"""
    
    def __init__(self, limit: str):
        super().__init__(
            message=f"请求频率过高，已达到限制: {limit}",
            error_code="RATE_LIMIT_EXCEEDED",
            details={"limit": limit},
            status_code=status.HTTP_429_TOO_MANY_REQUESTS
        )


class ValidationError(AgentException):
    """数据验证异常"""
    
    def __init__(self, field: str, reason: str):
        super().__init__(
            message=f"字段 {field} 验证失败: {reason}",
            error_code="VALIDATION_ERROR",
            details={"field": field, "reason": reason},
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY
        )


class DatabaseError(AgentException):
    """数据库异常"""
    
    def __init__(self, operation: str, reason: str):
        super().__init__(
            message=f"数据库操作 {operation} 失败: {reason}",
            error_code="DATABASE_ERROR",
            details={"operation": operation, "reason": reason},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


class ExternalServiceError(AgentException):
    """外部服务异常"""
    
    def __init__(self, service: str, reason: str):
        super().__init__(
            message=f"外部服务 {service} 调用失败: {reason}",
            error_code="EXTERNAL_SERVICE_ERROR",
            details={"service": service, "reason": reason},
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE
        )


class FileError(AgentException):
    """文件操作异常"""
    
    def __init__(self, operation: str, filename: str, reason: str):
        super().__init__(
            message=f"文件操作 {operation} 失败 ({filename}): {reason}",
            error_code="FILE_ERROR",
            details={"operation": operation, "filename": filename, "reason": reason},
            status_code=status.HTTP_400_BAD_REQUEST
        )


def create_error_response(
    error_code: str,
    message: str,
    details: Optional[Dict[str, Any]] = None,
    status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR
) -> JSONResponse:
    """创建标准错误响应"""
    
    content = {
        "error": {
            "code": error_code,
            "message": message,
            "details": details or {},
            "timestamp": str(int(__import__("time").time()))
        }
    }
    
    return JSONResponse(
        status_code=status_code,
        content=content
    )


async def agent_exception_handler(request: Request, exc: AgentException) -> JSONResponse:
    """智能体异常处理器"""
    logger.error(
        f"智能体异常: {exc.message}",
        extra={
            "error_code": exc.error_code,
            "details": exc.details,
            "path": request.url.path,
            "method": request.method,
            "client": request.client.host if request.client else None
        }
    )
    
    return create_error_response(
        error_code=exc.error_code,
        message=exc.message,
        details=exc.details,
        status_code=exc.status_code
    )


async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
    """HTTP异常处理器"""
    logger.warning(
        f"HTTP异常: {exc.detail}",
        extra={
            "status_code": exc.status_code,
            "path": request.url.path,
            "method": request.method,
            "client": request.client.host if request.client else None
        }
    )
    
    return create_error_response(
        error_code="HTTP_ERROR",
        message=exc.detail,
        status_code=exc.status_code
    )


async def validation_exception_handler(request: Request, exc: RequestValidationError) -> JSONResponse:
    """数据验证异常处理器"""
    errors = []
    for error in exc.errors():
        errors.append({
            "field": ".".join(str(x) for x in error["loc"]),
            "message": error["msg"],
            "type": error["type"]
        })
    
    logger.warning(
        f"数据验证失败: {len(errors)} 个错误",
        extra={
            "errors": errors,
            "path": request.url.path,
            "method": request.method,
            "client": request.client.host if request.client else None
        }
    )
    
    return create_error_response(
        error_code="VALIDATION_ERROR",
        message="请求数据验证失败",
        details={"errors": errors},
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY
    )


async def pydantic_validation_exception_handler(request: Request, exc: ValidationError) -> JSONResponse:
    """Pydantic验证异常处理器"""
    errors = []
    for error in exc.errors():
        errors.append({
            "field": ".".join(str(x) for x in error["loc"]),
            "message": error["msg"],
            "type": error["type"]
        })
    
    logger.warning(
        f"Pydantic验证失败: {len(errors)} 个错误",
        extra={
            "errors": errors,
            "path": request.url.path,
            "method": request.method,
        }
    )
    
    return create_error_response(
        error_code="VALIDATION_ERROR",
        message="数据模型验证失败",
        details={"errors": errors},
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY
    )


async def general_exception_handler(request: Request, exc: Exception) -> JSONResponse:
    """通用异常处理器"""
    # 记录完整的错误堆栈
    error_traceback = traceback.format_exc()
    
    logger.error(
        f"未处理的异常: {str(exc)}",
        extra={
            "exception_type": type(exc).__name__,
            "traceback": error_traceback,
            "path": request.url.path,
            "method": request.method,
            "client": request.client.host if request.client else None
        }
    )
    
    # 记录安全事件 (可能是攻击尝试)
    if isinstance(exc, (KeyError, AttributeError, TypeError)):
        log_security_event(
            "POTENTIAL_ATTACK",
            ip_address=request.client.host if request.client else None,
            path=request.url.path,
            exception=str(exc)
        )
    
    # 在生产环境中不暴露内部错误详情
    from app.core.config import get_settings
    settings = get_settings()
    
    if settings.environment == "production":
        return create_error_response(
            error_code="INTERNAL_SERVER_ERROR",
            message="服务暂时不可用，请稍后重试",
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )
    else:
        return create_error_response(
            error_code="INTERNAL_SERVER_ERROR",
            message=f"内部服务器错误: {str(exc)}",
            details={"traceback": error_traceback},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


def setup_exception_handlers(app: FastAPI):
    """设置异常处理器"""
    
    # 智能体异常
    app.add_exception_handler(AgentException, agent_exception_handler)
    
    # HTTP异常
    app.add_exception_handler(HTTPException, http_exception_handler)
    app.add_exception_handler(StarletteHTTPException, http_exception_handler)
    
    # 验证异常
    app.add_exception_handler(RequestValidationError, validation_exception_handler)
    app.add_exception_handler(ValidationError, pydantic_validation_exception_handler)
    
    # 通用异常 (必须放在最后)
    app.add_exception_handler(Exception, general_exception_handler)
    
    logger.info("✅ 异常处理器设置完成")


# 装饰器：异常捕获
def handle_exceptions(default_return=None):
    """异常处理装饰器"""
    def decorator(func):
        async def wrapper(*args, **kwargs):
            try:
                return await func(*args, **kwargs)
            except AgentException:
                raise  # 重新抛出智能体异常
            except Exception as e:
                logger.error(f"函数 {func.__name__} 执行失败: {str(e)}")
                if default_return is not None:
                    return default_return
                raise AgentException(f"操作失败: {str(e)}")
        
        return wrapper
    return decorator


# 导出
__all__ = [
    # 异常类
    "AgentException",
    "AgentNotFoundError",
    "AgentCreationError",
    "ModelError",
    "ToolError",
    "MemoryError",
    "AuthenticationError",
    "AuthorizationError",
    "RateLimitError",
    "ValidationError",
    "DatabaseError",
    "ExternalServiceError",
    "FileError",
    
    # 函数
    "create_error_response",
    "setup_exception_handlers",
    "handle_exceptions",
]